#pragma once
#include "comm.hpp"

namespace ns_util
{
    const std::string temp_path = "./temp/";

    // 此类为时间获取功能类
    class TimeUtil
    {
    public:
        // 此函数为获取系统时间戳
        static std::string GetTimeStap()
        {
            struct timeval _time;
            gettimeofday(&_time, nullptr);
            return std::to_string(_time.tv_sec);
        }
        // 此函数为获取毫秒时间戳
        static std::string GetTimeMs()
        {
            struct timeval _time;
            gettimeofday(&_time, nullptr);
            return std::to_string(_time.tv_sec * 1000 + _time.tv_usec / 1000);
        }
        // 此函数为获取日期和时间。格式为 "%Y-%m-%d %H:%M:%S"
        static std::string GetDayAndTime()
        {
            struct timeval _time;
            gettimeofday(&_time, nullptr);
            struct tm *t = gmtime(&_time.tv_sec); // 时间戳转化为UTC
            t->tm_hour += 8;                      // 转北京时间要加8
            std::string myFormat = "%Y-%m-%d %H:%M:%S";
            char mytime[30] = {0};
            strftime(mytime, sizeof(mytime), myFormat.c_str(), t); // 把时间戳按指定的格式转为字符串
            return std::string(mytime);
        }
    };
    // 此类为生成文件名的功能类
    class PathUtil
    {
    public:
        // 此函数为将file_name文件名 加上前缀和后缀
        // file_name:abcd
        // return: ./temp/abcd.cpp
        static std::string AddSuFFix(const std::string &file_name, const std::string &suffix)
        {
            std::string path_name = temp_path;
            path_name += file_name;
            path_name += suffix;
            return path_name;
        }
        // 此函数为生成.cpp后缀的源文件
        static std::string Src(const std::string &file_name)
        {
            return AddSuFFix(file_name, ".cpp");
        }
        // 此函数为生成.exe后缀的可执行文件
        static std::string Exe(const std::string &file_name)
        {
            return AddSuFFix(file_name, ".exe");
        }
        // 此函数为生成编译阶段的错误文件
        static std::string CompileError(const std::string &file_name)
        {
            return AddSuFFix(file_name, ".compile_error");
        }
        // 此函数为生成标准输入对应的文件
        static std::string Stdin(const std::string &file_name)
        {
            return AddSuFFix(file_name, ".stdin");
        }
        // 此函数为生成标准输出对应的文件
        static std::string Stdout(const std::string &file_name)
        {
            return AddSuFFix(file_name, ".stdout");
        }
        // 此函数为生成标准错误对应的文件
        static std::string Stderr(const std::string &file_name)
        {
            return AddSuFFix(file_name, ".stderr");
        }
    };

    // 此类为文件操作的功能类
    class FileUtil
    {
    public:
        // 此函数为检测某个文件是否存在
        static bool IsFileExists(const std::string &path_name)
        {
            struct stat st; // 结构体stat保存文件各种属性信息
            // stat函数可以获得一个文件的属性信息，将其保存到stat结构体中
            if (stat(path_name.c_str(), &st) == 0)
            {
                // 获取成功，文件存在
                return true;
            }
            return false;
        }
        // 此函数为生成唯一的文件名
        static std::string UniqFileName()
        {
            // 使用毫秒级时间戳+原子性递增唯一值形成唯一文件名
            static std::atomic_uint id(0);
            id++;
            std::string ms = TimeUtil::GetTimeMs();
            std::string uniq_id = std::to_string(id);
            return "file" + ms + "_" + uniq_id;
        }
        // 此函数为将code代码写入到文件中
        static bool WriteFile(const std::string &target, const std::string &text)
        {
            std::ofstream out(target);
            if (!out.is_open())
            {
                // 打开文件失败
                return false;
            }
            out.write(text.c_str(), text.size());
            out.close();
            return true;
        }
        // 此函数为读取文件的内容
        // text:输出型参数，将读取的文本内容放入text中
        // keep:是否添加按行读取后的行分隔符，默认为不添加
        static bool ReadFile(const std::string &target, std::string *text, bool keep = false)
        {
            (*text).clear();
            std::ifstream in(target);
            if (!in.is_open())
                return false;
            std::string line;
            while (std::getline(in, line))
            {
                (*text) += line;
                (*text) += (keep ? "\n" : "");
            }
            in.close();
            return true;
        }
    };
    class StringUtil
    {
        public:
            //此函数的功能为将字符串按照sep进行切割，并将切割结果放入out中
            static void SplitString(const std::string &str,std::vector<std::string>& out, std::string sep,bool flag = true)
            {
                if(flag)//去除连续间隔符
                    boost::split(out,str, boost::is_any_of(sep),boost::algorithm::token_compress_on);
                else
                    boost::split(out,str, boost::is_any_of(sep));
            }
    };

}
